VERSION --use-host-command 0.6

ARG DOCKERHUB_USER_SECRET=+secrets/DOCKERHUB_USER
ARG DOCKERHUB_TOKEN_SECRET=+secrets/DOCKERHUB_TOKEN
ARG DOCKERHUB_MIRROR
ARG DOCKERHUB_MIRROR_INSECURE=false
ARG DOCKERHUB_AUTH=true
FROM ..+earthly-integration-test-base \
    --DOCKERHUB_AUTH=$DOCKERHUB_AUTH \
    --DOCKERHUB_USER_SECRET=$DOCKERHUB_USER_SECRET \
    --DOCKERHUB_TOKEN_SECRET=$DOCKERHUB_TOKEN_SECRET \
    --DOCKERHUB_MIRROR=$DOCKERHUB_MIRROR \
    --DOCKERHUB_MIRROR_INSECURE=$DOCKERHUB_MIRROR_INSECURE

RUN apk add --update --no-cache \
    perl findutils

WORKDIR /test

all:
    BUILD +ga
    BUILD +experimental

ga:
    BUILD ./autocompletion+test-all \
        --DOCKERHUB_AUTH=$DOCKERHUB_AUTH \
        --DOCKERHUB_USER_SECRET=$DOCKERHUB_USER_SECRET \
        --DOCKERHUB_TOKEN_SECRET=$DOCKERHUB_TOKEN_SECRET \
        --DOCKERHUB_MIRROR=$DOCKERHUB_MIRROR \
        --DOCKERHUB_MIRROR_INSECURE=$DOCKERHUB_MIRROR_INSECURE
    BUILD ./scrub-https-credentials+all \
        --DOCKERHUB_AUTH=$DOCKERHUB_AUTH \
        --DOCKERHUB_USER_SECRET=$DOCKERHUB_USER_SECRET \
        --DOCKERHUB_TOKEN_SECRET=$DOCKERHUB_TOKEN_SECRET \
        --DOCKERHUB_MIRROR=$DOCKERHUB_MIRROR \
        --DOCKERHUB_MIRROR_INSECURE=$DOCKERHUB_MIRROR_INSECURE
    BUILD ./with-docker+all
    BUILD ./with-docker-compose+all
    BUILD ./with-docker-via-command+test
    BUILD ./dockerfile+test
    BUILD ./dockerfile2/subdir+test
    BUILD ./version+test-all \
        --DOCKERHUB_AUTH=$DOCKERHUB_AUTH \
        --DOCKERHUB_USER_SECRET=$DOCKERHUB_USER_SECRET \
        --DOCKERHUB_TOKEN_SECRET=$DOCKERHUB_TOKEN_SECRET \
        --DOCKERHUB_MIRROR=$DOCKERHUB_MIRROR \
        --DOCKERHUB_MIRROR_INSECURE=$DOCKERHUB_MIRROR_INSECURE
    BUILD ./locally-in-command+all \
        --DOCKERHUB_AUTH=$DOCKERHUB_AUTH \
        --DOCKERHUB_USER_SECRET=$DOCKERHUB_USER_SECRET \
        --DOCKERHUB_TOKEN_SECRET=$DOCKERHUB_TOKEN_SECRET \
        --DOCKERHUB_MIRROR=$DOCKERHUB_MIRROR \
        --DOCKERHUB_MIRROR_INSECURE=$DOCKERHUB_MIRROR_INSECURE
    BUILD ./import+build
    BUILD ./import+build-imported
    BUILD ./platform+test
    BUILD +privileged-test
    BUILD +copy-test
    BUILD +copy-test-verbose-output
    BUILD +cache-test
    BUILD +git-clone-test
    BUILD ./git-metadata+test \
        --DOCKERHUB_AUTH=$DOCKERHUB_AUTH \
        --DOCKERHUB_USER_SECRET=$DOCKERHUB_USER_SECRET \
        --DOCKERHUB_TOKEN_SECRET=$DOCKERHUB_TOKEN_SECRET \
        --DOCKERHUB_MIRROR=$DOCKERHUB_MIRROR \
        --DOCKERHUB_MIRROR_INSECURE=$DOCKERHUB_MIRROR_INSECURE
    BUILD ./git-ssh-server+all \
        --DOCKERHUB_AUTH=$DOCKERHUB_AUTH \
        --DOCKERHUB_USER_SECRET=$DOCKERHUB_USER_SECRET \
        --DOCKERHUB_TOKEN_SECRET=$DOCKERHUB_TOKEN_SECRET \
        --DOCKERHUB_MIRROR=$DOCKERHUB_MIRROR \
        --DOCKERHUB_MIRROR_INSECURE=$DOCKERHUB_MIRROR_INSECURE
    BUILD ./private-https+all \
        --DOCKERHUB_AUTH=$DOCKERHUB_AUTH \
        --DOCKERHUB_USER_SECRET=$DOCKERHUB_USER_SECRET \
        --DOCKERHUB_TOKEN_SECRET=$DOCKERHUB_TOKEN_SECRET \
        --DOCKERHUB_MIRROR=$DOCKERHUB_MIRROR \
        --DOCKERHUB_MIRROR_INSECURE=$DOCKERHUB_MIRROR_INSECURE
    BUILD +builtin-args-test
    BUILD +builtin-args-invalid-default-test
    BUILD +builtin-args-invalid-pass-test
    BUILD +builtin-args-cli-tests
    BUILD +smoke-test
    BUILD ./config+test \
        --DOCKERHUB_AUTH=$DOCKERHUB_AUTH \
        --DOCKERHUB_USER_SECRET=$DOCKERHUB_USER_SECRET \
        --DOCKERHUB_TOKEN_SECRET=$DOCKERHUB_TOKEN_SECRET \
        --DOCKERHUB_MIRROR=$DOCKERHUB_MIRROR \
        --DOCKERHUB_MIRROR_INSECURE=$DOCKERHUB_MIRROR_INSECURE
    BUILD ./invalid+test-all \
        --DOCKERHUB_AUTH=$DOCKERHUB_AUTH \
        --DOCKERHUB_USER_SECRET=$DOCKERHUB_USER_SECRET \
        --DOCKERHUB_TOKEN_SECRET=$DOCKERHUB_TOKEN_SECRET \
        --DOCKERHUB_MIRROR=$DOCKERHUB_MIRROR \
        --DOCKERHUB_MIRROR_INSECURE=$DOCKERHUB_MIRROR_INSECURE
    BUILD ./secret-provider-config+test-all \
        --DOCKERHUB_AUTH=$DOCKERHUB_AUTH \
        --DOCKERHUB_USER_SECRET=$DOCKERHUB_USER_SECRET \
        --DOCKERHUB_TOKEN_SECRET=$DOCKERHUB_TOKEN_SECRET \
        --DOCKERHUB_MIRROR=$DOCKERHUB_MIRROR \
        --DOCKERHUB_MIRROR_INSECURE=$DOCKERHUB_MIRROR_INSECURE
    BUILD ./shell-out+test-all \
        --DOCKERHUB_AUTH=$DOCKERHUB_AUTH \
        --DOCKERHUB_USER_SECRET=$DOCKERHUB_USER_SECRET \
        --DOCKERHUB_TOKEN_SECRET=$DOCKERHUB_TOKEN_SECRET \
        --DOCKERHUB_MIRROR=$DOCKERHUB_MIRROR \
        --DOCKERHUB_MIRROR_INSECURE=$DOCKERHUB_MIRROR_INSECURE
    BUILD +excludes-test
    BUILD +secrets-test
    BUILD +build-arg-test
    BUILD +build-arg-explicit-global-test
    BUILD +build-arg-dynamic-with-empty-base
    BUILD +lc-test
    BUILD +from-expose-test
    BUILD +scratch-test
    BUILD +build-earthly-test
    BUILD +host-bind-test
    BUILD +remote-test
    BUILD +transitive-args-test
    BUILD +transitive-args-test2
    BUILD +non-transitive-args-test
    BUILD +star-test
    BUILD +dockerfile-test
    BUILD +fail-test
    BUILD +fail-push-test
    BUILD +allow-privileged-test
    BUILD +allow-privileged-import-test
    BUILD +reject-privileged-import-test
    BUILD +required-arg-test
    BUILD +push-test
    BUILD +gen-dockerfile-test
    BUILD +chown-test
    BUILD +dotenv-test
    BUILD +env-test
    BUILD +no-cache-local-artifact-test
    BUILD +empty-git-test
    BUILD +escape-test
    BUILD +escape-test --EARTHFILE=escape-v0.5.earth
    BUILD +escape-dir-test
    BUILD +fail-invalid-artifact-test
    BUILD +target-first-line
    BUILD +absolute-reference-with-relative
    BUILD +end-comment
    BUILD +if-exists
    BUILD +file-copying
    BUILD +run-no-cache
    BUILD +save-artifact-file-as-dot
    BUILD +save-artifact-dir-as-dot
    BUILD +save-artifact-dont-overwrite
    BUILD +save-artifact-force-overwrite
    BUILD +save-artifact-after-push
    BUILD +save-artifact-selective
    BUILD +save-artifact-selective-legacy
    BUILD +save-artifact-selective-referencing-remote
    BUILD +save-remote-artifact-selective-legacy
    BUILD +save-remote-artifact-selective
    BUILD +push-build
    BUILD +build-arg-repeat
    BUILD +if
    BUILD +for
    BUILD +first-command
    BUILD +platform-output
    BUILD +command
    BUILD +command-explicit-global
    BUILD +duplicate
    BUILD +reserved
    BUILD +quotes-test
    BUILD +new-args
    BUILD +import
    BUILD +infinite-recursion
    BUILD +from-dockerfile-arg
    BUILD +cache-mount-arg
    BUILD +true-false-flag
    BUILD +true-false-flag-invalid
    BUILD +dont-save-indirect-remote-artifact
    BUILD +sequential-locally-test
    BUILD +version-flag-test
    BUILD +implicit-ignores
    BUILD +help
    BUILD +cache-cmd
    BUILD +ls
    BUILD +ls-subdir
    BUILD +ssh
    BUILD +host
    BUILD +host-invalid
    BUILD +mtime
    BUILD +server
    BUILD +build-after-from

# tests that only run on linux amd64
# Note: this target is used to validate the USERPLATFORM user arg,
# and should not be used to programatically detect if this should be
# run or not.
ga-linux-amd64:
    BUILD +user-arg-test

experimental:
    BUILD ./dind-auto-install+all

ast-test-input:
    FROM alpine:3.15
    COPY ./*.earth ./
    COPY ./with-docker/Earthfile ./with-docker.earth
    COPY ./with-docker-compose/Earthfile ./with-docker-compose.earth
    SAVE ARTIFACT ./*.earth

privileged-test:
    DO +RUN_EARTHLY --earthfile=privileged.earth --extra_args="--allow-privileged" --target=+test

copy-test:
    RUN mkdir -p in/sub/1 in/sub/2 && \
        echo "root" > in/root && \
        echo "1" > in/sub/1/file && \
        echo "2" > in/sub/2/file && \
        echo "sub" > in/sub/file
    DO +RUN_EARTHLY --earthfile=copy.earth

copy-test-verbose-output:
    RUN mkdir -p subdir/a.txt && \
        echo -n "a" > a.txt && \
        echo -n "alpha" > alpha.txt && \
        echo -n "beta" > subdir/a.txt/beta.txt

    # Setup a test that runs earthly twice; both instances of earthly must be run
    # back to back as the file caching logic references the directories inode ID while constructing
    # the shared cache key.
    RUN echo "#!/bin/sh
set -x
earthly --config \$earthly_config --verbose +all 2>output.txt;
earthly --config \$earthly_config --verbose +all 2>output2.txt;
" >/tmp/multiple-earthly-script && chmod +x /tmp/multiple-earthly-script

    DO +RUN_EARTHLY --earthfile=copy-verbose.earth --exec_cmd=/tmp/multiple-earthly-script

    # test that the first run sends a.txt and doesn't send any non-referenced files
    RUN cat output.txt
    RUN cat output.txt | grep 'sent data for a.txt (1 B)'
    RUN if grep "sent data for alpha.txt" output.txt >/dev/null; then echo "alpha.txt should not have been sent"; exit 1; fi
    RUN if grep "sent data for .*beta.txt" output.txt >/dev/null; then echo "beta.txt should not have been sent"; exit 1; fi

    # test that the second run did not resend a.txt (or any other non-referenced files)
    RUN cat output2.txt
    RUN if grep "sent data for a.txt" output2.txt >/dev/null; then echo "a.txt should not have been sent"; exit 1; fi
    RUN if grep "sent data for alpha.txt" output2.txt >/dev/null; then echo "alpha.txt should not have been sent"; exit 1; fi
    RUN if grep "sent data for .*beta.txt" output2.txt >/dev/null; then echo "beta.txt should not have been sent"; exit 1; fi

cache-test:
    # Test that a file can be passed between runs through the mounted cache.
    DO +RUN_EARTHLY --earthfile=cache1.earth --target=+test-pass-file --use_tmpfs=false
    DO +RUN_EARTHLY --earthfile=cache2.earth --target=+test-pass-file --use_tmpfs=false
    # Test that a change to the contents of the mount does not cause a cache bust if everything else
    # is the same.
    DO +RUN_EARTHLY --earthfile=cache1.earth --target=+test-no-bust-on-change --use_tmpfs=false
    DO +RUN_EARTHLY --earthfile=cache2.earth --target=+test-no-bust-on-change --use_tmpfs=false  # make a change
    DO +RUN_EARTHLY --earthfile=cache1.earth --target=+test-no-bust-on-change --use_tmpfs=false \
        --post_command=">output.txt 2>&1" # check that all is still cached if re-running the prev version
    RUN cat output.txt
    RUN cat output.txt | grep '\*cached\* --> RUN echo hey'

git-clone-test:
    DO +RUN_EARTHLY --earthfile=git-clone.earth --target=+test

builtin-args-test:
    DO +RUN_EARTHLY --earthfile=builtin-args.earth --target=+builtin-args-test

builtin-args-invalid-default-test:
    DO +RUN_EARTHLY --earthfile=builtin-args-invalid-default.earth --should_fail=true --target=+test --output_contains="arg default value supplied for built-in ARG"

builtin-args-invalid-pass-test:
    DO +RUN_EARTHLY --earthfile=builtin-args-invalid-pass.earth --should_fail=true --target=+test --output_contains="value cannot be specified for built-in build arg EARTHLY_VERSION"

builtin-args-cli-tests:
    DO +RUN_EARTHLY --earthfile=builtin-args.earth --should_fail=true --extra_args="--build-arg EARTHLY_VERSION=123" --target=+builtin-args-test \
        --output_contains="cannot be passed on the command line"

smoke-test:
    DO +RUN_EARTHLY --earthfile=smoke.earth --target=+test

excludes-test:
    RUN touch exclude-me.txt
    RUN touch do-not-exclude-me.txt
    RUN echo 'exclude-me.txt' > .earthlyignore
    DO +RUN_EARTHLY --earthfile=excludes.earth --target=+test

secrets-test:
    ENV SECRET1=foo
    ENV SECRET2=wrong
    RUN echo -n "secretfilecontents" > /root/my-secret-file
    DO +RUN_EARTHLY \
        --earthfile=secrets.earth \
        --extra_args="--secret SECRET1 --secret SECRET2=bar --secret-file SECRET3=~/my-secret-file --build-arg SECRET_ID=\"\" --build-arg SECRET_ID_2=\"\"" \
        --target=+test
    DO +RUN_EARTHLY \
        --earthfile=secrets.earth \
        --extra_args="--secret SECRET1 --secret SECRET2=bar --build-arg SECRET_ID=\"\" --build-arg SECRET_ID_2=\"\"" \
        --target=+test \
        --should_fail=true \
        --output_contains="unable to lookup secret SECRET3: not found"

build-arg-test:
    DO +RUN_EARTHLY --earthfile=build-arg.earth

build-arg-explicit-global-test:
    DO +RUN_EARTHLY --earthfile=build-arg-explicit-global.earth --target=+test-success
    DO +RUN_EARTHLY --should_fail=true --earthfile=build-arg-explicit-global.earth \
        --target=+test-failure \
        --output_contains="invalid ARG arguments.*: global ARG can only be set in the base target"

build-arg-dynamic-with-empty-base:
    DO +RUN_EARTHLY --earthfile=build-arg-dynamic-with-empty-base.earth --target=+test

#this test only works under linux/amd64
user-arg-test:
    DO +RUN_EARTHLY --earthfile=user-arg.earth

lc-test:
    DO +RUN_EARTHLY --earthfile=lc.earth --target=+test

from-expose-test:
    DO +RUN_EARTHLY --earthfile=from-expose.earth --extra_args="--no-output" --target=+test

scratch-test:
    DO +RUN_EARTHLY --earthfile=scratch-test.earth --extra_args="--no-output" --target=+test

build-earthly-test:
    # Test that build.earth is supported.
    COPY smoke.earth ./build.earth
    RUN --privileged \
        --entrypoint \
        --mount=type=tmpfs,target=/tmp/earthly \
        -- +test

host-bind-test:
    RUN mkdir /bind-test
    RUN echo "a" > /bind-test/a.txt
    DO +RUN_EARTHLY --earthfile=host-bind.earth --target=+test
    RUN test -f /bind-test/b.txt
    RUN cat /bind-test/b.txt

remote-test:
    ENV GIT_URL_INSTEAD_OF="https://github.com/=git@github.com:"
    RUN --privileged \
        --entrypoint \
        --mount=type=tmpfs,target=/tmp/earthly \
        -- --no-output github.com/earthly/hello-world:main+hello
    RUN --privileged \
        --entrypoint \
        --mount=type=tmpfs,target=/tmp/earthly \
        -- --no-output github.com/earthly/test-remote/privileged:main+locally && \
        ls /tmp/hostname.3d4b1831-c07e-4b2d-805e-2b8ce578bb50
    RUN --privileged \
        --entrypoint \
        --mount=type=tmpfs,target=/tmp/earthly \
        -- --no-output github.com/earthly/test-remote/builtin-args:main+test

transitive-args-test:
    DO +RUN_EARTHLY --earthfile=transitive-args.earth --extra_args="--build-arg SOMEARG=xyz" --target=+test
    RUN ls
    RUN test -f ./abc
    RUN test -f ./xyz
    RUN test ! -f ./default
    RUN cat ./abc | grep abc
    RUN cat ./xyz | grep xyz

transitive-args-test2:
    DO +RUN_EARTHLY --earthfile=transitive-args.earth --target=+test
    RUN ls
    RUN test -f ./abc && test -f ./default
    RUN cat ./abc | grep abc
    RUN cat ./default | grep default

non-transitive-args-test:
    COPY non-transitive-args1.earth ./Earthfile
    COPY non-transitive-args2.earth ./subdir/Earthfile
    # Should not override if transitive and corssing project boundaries.
    RUN --privileged \
        --entrypoint \
        --mount=type=tmpfs,target=/tmp/earthly \
        -- --build-arg SOMEARG=def +test
    RUN ls ./subdir
    RUN test -f ./subdir/default && test ! -f ./subdir/def && test ! -f ./subdir/abc
    RUN rm ./subdir/default
    # Should override, if override is direct.
    RUN --privileged \
        --entrypoint \
        --mount=type=tmpfs,target=/tmp/earthly \
        -- --build-arg SOMEARG=xyz ./subdir+arg-target
    RUN ls ./subdir
    RUN test -f ./subdir/xyz && test ! -f ./subdir/default
    RUN --privileged \
        --entrypoint \
        --mount=type=tmpfs,target=/tmp/earthly \
        -- +direct
    RUN ls ./subdir
    RUN test -f ./subdir/direct && test ! -f ./subdir/default

star-test:
    RUN touch a.txt b.txt c.nottxt
    DO +RUN_EARTHLY --earthfile=star.earth --target=+test

# TODO: This does not pass.
star-test-todo:
    RUN touch a.txt b.txt c.nottxt
    DO +RUN_EARTHLY --earthfile=star.earth --target=+test --use_tmpfs=false
    RUN echo "a change" > c.nottxt
    DO +RUN_EARTHLY --earthfile=star.earth --target=+test --use_tmpfs=false \
        --post_command=">output.txt"
    RUN cat output.txt
    RUN cached_lines=$(cat output.txt | grep cached | wc -l); \
        echo "cached_lines=$cached_lines"; \
        test "$cached_lines" == "6"

dockerfile-test:
    COPY dockerfile/* ./
    RUN --privileged \
        --entrypoint \
        --mount=type=tmpfs,target=/tmp/earthly \
        -- --no-output +test

fail-test:
    DO +RUN_EARTHLY --earthfile=fail.earth --should_fail=true --target=+test --post_command="2>output.txt"
    RUN cat output.txt
    # The output of the failed command should have been printed twice.
    RUN cat output.txt | grep 'ZmFpbCA3YjcyZTAyNC01ZTIxLTRlMWItOTZlNC02NTVjMzk4NzYxMDcK' | test "$(wc -l)" -eq 2
    RUN cat output.txt | grep 'Repeating the output of the command that caused the failure'

allow-privileged-test:
    # test that privileged-tasks in remote repos dont run
    DO +RUN_EARTHLY --earthfile=allow-privileged.earth --should_fail=true --extra_args="--allow-privileged" -target=+reject-privileged-in-remote-repo-triggered-by-from-locally
    DO +RUN_EARTHLY --earthfile=allow-privileged.earth --should_fail=true --extra_args="--allow-privileged" -target=+reject-privileged-in-remote-repo-triggered-by-from-privileged
    DO +RUN_EARTHLY --earthfile=allow-privileged.earth --should_fail=true --extra_args="--allow-privileged" -target=+reject-privileged-in-remote-repo-triggered-by-copy-locally
    DO +RUN_EARTHLY --earthfile=allow-privileged.earth --should_fail=true --extra_args="--allow-privileged" -target=+reject-privileged-in-remote-repo-triggered-by-copy-privileged
    DO +RUN_EARTHLY --earthfile=allow-privileged.earth --should_fail=true --extra_args="--allow-privileged" -target=+reject-privileged-in-remote-repo-triggered-by-build-locally
    DO +RUN_EARTHLY --earthfile=allow-privileged.earth --should_fail=true --extra_args="--allow-privileged" -target=+reject-privileged-in-remote-repo-triggered-by-build-privileged
    DO +RUN_EARTHLY --earthfile=allow-privileged.earth --should_fail=true --extra_args="--allow-privileged" -target=+reject-dedup
    # test allowed-privileged tasks in remote repos work
    DO +RUN_EARTHLY --earthfile=allow-privileged.earth --extra_args="--allow-privileged" --target=+allow-all

allow-privileged-import-test:
    RUN mkdir -p a/really/deep/subdir && echo "subdirprivileged:
    FROM alpine:latest
    RUN --privileged cat /proc/self/status | grep CapEff > output
    SAVE ARTIFACT output proc-status
" > a/really/deep/subdir/Earthfile
    DO +RUN_EARTHLY --earthfile=allow-privileged-import.earth --extra_args="--allow-privileged" --target=+test

reject-privileged-import-test:
    DO +RUN_EARTHLY --earthfile=reject-privileged-import.earth --should_fail=true --extra_args="--allow-privileged" --target=+test-reject-copy
    DO +RUN_EARTHLY --earthfile=reject-privileged-import.earth --should_fail=true --extra_args="--allow-privileged" --target=+test-reject-cmd

required-arg-test:
    # test that build arg is required
    DO +RUN_EARTHLY --earthfile=required-args.earth --should_fail=true --target=+test-accept-valid-required-arg
    # test parser rejects required arg with default value
    DO +RUN_EARTHLY --earthfile=required-args.earth --should_fail=true --target=+test-reject-default-val-required-arg
    DO +RUN_EARTHLY --earthfile=required-args.earth --should_fail=true --extra_args="--build-arg req=val" --target=+test-reject-default-val-required-arg
    # test valid required arg with build-arg provided
    DO +RUN_EARTHLY --earthfile=required-args.earth --extra_args="--build-arg req=val" --target=+test-accept-valid-required-arg
    DO +RUN_EARTHLY --earthfile=required-args.earth --target=+test-accept-valid-required-arg-build-arg-in-earthfile

fail-push-test:
    # test that an error code is correctly returned
    DO +RUN_EARTHLY --earthfile=fail.earth --should_fail=true --extra_args="--push" --target=+test-push \
        --output_contains="this-too-will-fail"

fail-invalid-artifact-test:
    # test that the artifact fails to be copied
    DO +RUN_EARTHLY --earthfile=fail-invalid-artifact.earth --should_fail=true --target="--artifact +test/foo /tmp/stuff" \
        --output_contains="cannot save artifact +test/foo, since it does not exist"

push-test:
    DO +RUN_EARTHLY --earthfile=push.earth --target=+push-test \
        --post_command="2>&1 | grep '(disabled)'"
    DO +RUN_EARTHLY --earthfile=push.earth --extra_args="--push" --target=+push-test \
        --post_command="2>&1 | grep 'hello world'"

private-image-test:
    FROM earthly/private-test:latest
    RUN --entrypoint echo hello world

gen-dockerfile-test:
    DO +RUN_EARTHLY --earthfile=gen-dockerfile.earth --extra_args="--no-output" --target=+all

comments-test:
    DO +RUN_EARTHLY --earthfile=comments.earth --extra_args="--no-output" --target=+test

chown-test:
    RUN echo "test" > ./a.txt
    DO +RUN_EARTHLY --earthfile=chown.earth --target=+test

dotenv-test:
    RUN echo "TEST_ENV_1=abracadabra" >.env
    RUN echo "TEST_ENV_2=foo" >>.env
    RUN echo "TEST_ENV_3=bar" >>.env
    DO +RUN_EARTHLY --earthfile=dotenv.earth --extra_args="--no-output" --target=+test
    # Smoke test that no .env file does not result in an error.
    RUN mv .env .some-other-env
    DO +RUN_EARTHLY --earthfile=dotenv.earth --extra_args="--no-output" --target=+test-no-dotenv
    DO +RUN_EARTHLY --earthfile=dotenv.earth --extra_args="--no-output --env-file .some-other-env" --target=+test
    DO +RUN_EARTHLY --earthfile=dotenv.earth --extra_args="--no-output" --pre_command="export EARTHLY_ENV_FILE=.some-other-env" --target=+test
    DO +RUN_EARTHLY --earthfile=dotenv.earth --extra_args="--no-output --env-file .this-should-fail" --should_fail="true" --target=+test
    DO +RUN_EARTHLY --earthfile=dotenv.earth --extra_args="--no-output" --pre_command="export EARTHLY_ENV_FILE=.this-too-should-fail" --should_fail="true" --target=+test

    # --env-file takes preceddence
    DO +RUN_EARTHLY --earthfile=dotenv.earth --extra_args="--no-output --env-file .some-other-env" --pre_command="export EARTHLY_ENV_FILE=.this-should-be-ignored" --target=+test


env-test:
    DO +RUN_EARTHLY --earthfile=env.earth --extra_args="--no-output" --target=+test

no-cache-local-artifact-test:
    DO +RUN_EARTHLY --earthfile=no-cache-local-artifact.earth --use_tmpfs=false --extra_args="--no-cache" --target=+test
    RUN mv file.txt old.txt
    DO +RUN_EARTHLY --earthfile=no-cache-local-artifact.earth --use_tmpfs=false --extra_args="--no-cache" --target=+test
    RUN ! diff file.txt old.txt

empty-git-test:
    RUN git init
    DO +RUN_EARTHLY --earthfile=empty-git.earth --extra_args="--no-output" --target=+test-empty
    RUN git remote add origin https://github.com/earthly/earthly.git
    DO +RUN_EARTHLY --earthfile=empty-git.earth --extra_args="--no-output" --target=+test-origin-no-hash

escape-test:
    ARG EARTHFILE=escape.earth
    RUN printf "content" >file-with-+.txt
    RUN printf "content" >regular-file.txt
    DO +RUN_EARTHLY --earthfile="$EARTHFILE"

escape-dir-test:
    RUN mkdir ./dir-with-+-in-it
    COPY escape-dir2.earth ./dir-with-+-in-it/Earthfile
    DO +RUN_EARTHLY --earthfile=escape-dir1.earth --extra_args="--no-output" --target=+test

eine-test-base:
    FROM docker:19.03.12-dind
    RUN apk --update --no-cache add git
    COPY ../..+earthly/earthly /usr/local/bin/
    ENV EARTHLY_BUILDKIT_IMAGE=earthly/buildkitd:dind-test
    WORKDIR /test

eine-smoke-test:
    FROM +eine-test-base
    COPY smoke.earth ./Earthfile
    WITH DOCKER --load earthly/buildkitd:dind-test=../../buildkitd+buildkitd
        RUN earthly +test
    END

eine-privileged-test:
    FROM +eine-test-base
    COPY privileged.earth ./Earthfile
    WITH DOCKER --load earthly/buildkitd:dind-test=../../buildkitd+buildkitd
        RUN earthly --allow-privileged +test
    END

target-first-line:
    DO +RUN_EARTHLY --earthfile=target-first-line.earth --extra_args="--no-output" --target=+test

absolute-reference-with-relative:
    RUN mkdir -p /a/path/to/test/subdir
    # create a base Earthfile which is referenced by target-absolute-reference.earth
    RUN echo -e "FROM alpine:3.15\nRUN mkdir -p /dir/from/base" > /a/path/to/test/Earthfile
    DO +RUN_EARTHLY --earthfile=absolute-reference-with-relative.earth --earthfile_dest=/a/path/to/test/subdir/Earthfile --extra_args="--no-output" --target=/a/path/to/test/subdir+test

end-comment:
    DO +RUN_EARTHLY --earthfile=end-comment.earth --target=+test

if-exists:
    DO +RUN_EARTHLY --earthfile=if-exists.earth --target=+save-exist-local
    DO +RUN_EARTHLY --earthfile=if-exists.earth --should_fail=true --target=+save-not-exist \
      --output_contains="save-not-exist"
    DO +RUN_EARTHLY --earthfile=if-exists.earth --should_fail=true --target=+copy-not-exist \
      --output_contains="copy-not-exist"
    DO +RUN_EARTHLY --earthfile=if-exists.earth --should_fail=true --target=+bad-wildcard-copy \
      --output_contains="bad-wildcard-copy"
    DO +RUN_EARTHLY --earthfile=if-exists.earth --should_fail=true --target=+bad-wildcard-save \
      --output_contains="bad-wildcard-save"
    RUN mkdir in && \
        echo "this-file-does-exist" > ./in/this-file-does-exist && \
        echo "so-does-this-one" > so-does-this-one 
    DO +RUN_EARTHLY --earthfile=if-exists.earth --target=+classic-copy-exists
    DO +RUN_EARTHLY --earthfile=if-exists.earth --target=+classic-copy-not-exist

file-copying:
    DO +RUN_EARTHLY --earthfile=file-copying.earth

    RUN find out-glob -printf '%P\n' | sort > result-glob
    RUN ls -la out-glob
    RUN diff -ws expected-glob result-glob

    RUN find out-dot -printf '%P\n' | sort > result-dot
    RUN ls -la out-dot
    RUN diff -ws expected-dot result-dot

    RUN find out-dot-slash -printf '%P\n' | sort > result-dot-slash
    RUN ls -la out-dot-slash
    RUN diff -ws expected-dot-slash result-dot-slash

    RUN find out-sub -printf '%P\n' | sort > result-sub
    RUN ls -la out-sub
    RUN diff -ws expected-sub result-sub

    RUN find out-sub-glob -printf '%P\n' | sort > result-sub-glob
    RUN ls -la out-sub-glob
    RUN diff -ws expected-sub-glob result-sub-glob

    RUN find out-dot-single -printf '%P\n' | sort > result-dot-single
    RUN ls -la out-dot-single
    RUN diff -ws expected-dot-single result-dot-single

    RUN find out-rel-single -printf '%P\n' | sort > result-rel-single
    RUN ls -la out-rel-single
    RUN diff -ws expected-rel-single result-rel-single

    RUN find out-src-dest-file-rename -printf '%P\n' | sort > result-src-dest-file-rename
    RUN ls -la out-src-dest-file-rename
    RUN diff -ws expected-src-dest-file-rename result-src-dest-file-rename

    RUN find out-src-dest-dir-rename -printf '%P\n' | sort > result-src-dest-dir-rename
    RUN ls -la out-src-dest-dir-rename
    RUN diff -ws expected-src-dest-dir-rename result-src-dest-dir-rename

    # Saving the root dir is not allowed. This should fail.
    DO +RUN_EARTHLY --earthfile=file-copying.earth --should_fail=true --target=+test-dot-scratch

save-artifact-dont-overwrite:
    RUN --no-cache echo hello > important-data

    DO +RUN_EARTHLY --should_fail=true --earthfile=save-artifact-dont-overwrite.earth --extra_args="--version-flag-overrides=require-force-for-unsafe-saves" \
        --target=+dont-overwrite-abs-ref --post_command="> /tmp/output 2>&1"
    RUN cat /tmp/output | grep 'Error.*path must be located under'

    DO +RUN_EARTHLY --should_fail=true --earthfile=save-artifact-dont-overwrite.earth --extra_args="--version-flag-overrides=require-force-for-unsafe-saves" \
        --target=+dont-overwrite-rel-ref --post_command="> /tmp/output 2>&1"
    RUN cat /tmp/output | grep 'Error.*path must be located under'

    DO +RUN_EARTHLY --should_fail=true --earthfile=save-artifact-dont-overwrite.earth --extra_args="--version-flag-overrides=require-force-for-unsafe-saves" \
        --target=+dont-overwrite-rel-other-ref --post_command="> /tmp/output 2>&1"
    RUN cat /tmp/output | grep 'Error.*path must be located under'

    DO +RUN_EARTHLY --should_fail=true --earthfile=save-artifact-dont-overwrite.earth --extra_args="--version-flag-overrides=require-force-for-unsafe-saves" \
        --target=+dont-overwrite-root --post_command="> /tmp/output 2>&1"
    RUN cat /tmp/output | grep 'Error.*path must be located under'

    DO +RUN_EARTHLY --should_fail=true --earthfile=save-artifact-dont-overwrite.earth --extra_args="--version-flag-overrides=require-force-for-unsafe-saves" \
        --target=+dont-overwrite-root2 --post_command="> /tmp/output 2>&1"
    RUN cat /tmp/output | grep 'Error.*path must be located under'

    DO +RUN_EARTHLY --should_fail=true --earthfile=save-artifact-dont-overwrite.earth --extra_args="--version-flag-overrides=require-force-for-unsafe-saves" \
        --target=+dont-overwrite-root3 --post_command="> /tmp/output 2>&1"
    RUN cat /tmp/output | grep 'Error.*path must be located under'

    RUN ls important-data

save-artifact-force-overwrite:
    RUN --no-cache echo hello > /root/important-data
    DO +RUN_EARTHLY --earthfile=save-artifact-overwrite.earth --extra_args="--version-flag-overrides=require-force-for-unsafe-saves" --target=+overwrite-root
    RUN cat /root/base | grep 88716877-039f-4dea-8ec3-84eb64f326c5
    RUN cat /root/sub/data1 | grep ff42c40d-034a-4855-8db7-febfa7322576
    RUN cat /root/sub/data2 | grep 2b4a653d-cdf6-4574-ac5e-f02bb6993365
    RUN ! ls /root/important-data

save-artifact-file-as-dot:
    DO +RUN_EARTHLY --earthfile=save-artifact-dot.earth --target=+save-local-file-as-dot
    RUN cat uuid | grep eeee5a95-1506-428f-8ef0-94bbad5bd22b

save-artifact-dir-as-dot:
    DO +RUN_EARTHLY --earthfile=save-artifact-dot.earth --target=+save-local-dir-as-dot
    RUN cat the-data/file1 | grep 7be91098-1823-41df-911b-2a8907fe5da7
    RUN cat the-data/file2 | grep b0359c17-d08b-411c-9db7-1333ef3673d0

run-no-cache:
    # Run twice to allow the second one to attempt to cache things
    DO +RUN_EARTHLY --earthfile=run-no-cache.earth --use_tmpfs=false --target=+test
    # Fail if we cached any of the motd2 lines, which are after the --no-cache
    DO +RUN_EARTHLY --earthfile=run-no-cache.earth --use_tmpfs=false --target=+test \
        --grep_flags="-v" --output_contains="\\\*cached\\\* --> .* motd2"

    # Run twice to allow the second one to attempt to cache things
    DO +RUN_EARTHLY --earthfile=run-no-cache.earth --use_tmpfs=false --target=+test-from
    # Fail if we cached any of the COPY motd2 lines, which are after the --no-cache
    DO +RUN_EARTHLY --earthfile=run-no-cache.earth --use_tmpfs=false --target=+test-from \
        --grep_flags="-v" --output_contains="\\\*cached\\\* --> .*motd2 \\\.\\\//"

save-artifact-after-push:
    # test that save after push is a thing
    DO +RUN_EARTHLY --earthfile=save-artifact-after-push.earth --target=+test

    # test that cant copy saved after push
    DO +RUN_EARTHLY --earthfile=save-artifact-after-push.earth --should_fail="true" --target=+copy-test \
        --output_contains="not found"

save-artifact-selective-test1:
    DO +RUN_EARTHLY --earthfile=save-artifact-selective.earth --target=+test1
    RUN test   -f a && \
        test   -f b && \
        test ! -f c && \
        test ! -f d && \
        test ! -f e

save-artifact-selective-test2:
    DO +RUN_EARTHLY --earthfile=save-artifact-selective.earth --target=+test2
    RUN test ! -f a && \
        test ! -f b && \
        test   -f c && \
        test ! -f d && \
        test ! -f e

save-artifact-selective-test3:
    DO +RUN_EARTHLY --earthfile=save-artifact-selective.earth --target=+test3
    RUN test ! -f a && \
        test ! -f b && \
        test ! -f c && \
        test   -f d && \
        test ! -f e

save-artifact-selective-test4:
    DO +RUN_EARTHLY --earthfile=save-artifact-selective.earth --target=+test4
    RUN test ! -f a && \
        test ! -f b && \
        test ! -f c && \
        test ! -f d && \
        test   -f e

save-artifact-selective-test5:
    DO +RUN_EARTHLY --earthfile=save-artifact-selective.earth --target=+test5
    RUN test ! -f a && \
        test ! -f b && \
        test ! -f c && \
        test ! -f d && \
        test ! -f e && \
        test ! -f test5sub && \
        test   -f test5

save-artifact-selective:
    # test that the `--referenced-save-only` feature only saves referenced artifacts
    BUILD +save-artifact-selective-test1
    BUILD +save-artifact-selective-test2
    BUILD +save-artifact-selective-test3
    BUILD +save-artifact-selective-test4
    BUILD +save-artifact-selective-test5

save-artifact-selective-legacy:
    RUN env | grep EARTHLY
    DO +RUN_EARTHLY --earthfile=save-artifact-legacy.earth --target=+all
    RUN test ! -f a && \
        test   -f b && \
        test   -f c && \
        test   -f d && \
        test   -f e && \
        test   -f f && \
        test ! -d output && \
        test ! -f output/testfile && \    # THIS FAILED
        test ! -f testfile

save-artifact-selective-referencing-remote-test1:
    DO +RUN_EARTHLY --earthfile=save-artifact-selective-remote.earth --target=+test1
    RUN test   -f a && \
        test ! -f b && \
        test ! -f c && \
        test ! -d output && \
        test ! -f output/testfile && \
        test ! -f testfile

save-artifact-selective-referencing-remote-test2:
    DO +RUN_EARTHLY --earthfile=save-artifact-selective-remote.earth --target=+test2
    RUN test ! -f a && \
        test   -f b && \
        test ! -f c && \
        test ! -d output && \
        test ! -f output/testfile && \
        test ! -f testfile

save-artifact-selective-referencing-remote-test3:
    DO +RUN_EARTHLY --earthfile=save-artifact-selective-remote.earth --target=+test3
    RUN test ! -f a && \
        test ! -f b && \
        test   -f c && \
        test   -d output && \
        test   -f output/testfile && \
        test ! -f testfile

save-artifact-selective-referencing-remote:
    BUILD +save-artifact-selective-referencing-remote-test1
    BUILD +save-artifact-selective-referencing-remote-test2
    BUILD +save-artifact-selective-referencing-remote-test3

save-remote-artifact-selective-legacy:
    DO +RUN_EARTHLY --target=github.com/earthly/test-remote/output/no-version:main+savelocal
    # if it were to be saved, it should show up under output/testfile; but we're going to check for
    # a) no output directory (which also means output/testfile doesn't exist), and
    # b) that ./testfile wasn't accidentally created.
    RUN test ! -d output && \
        test ! -f testfile

save-remote-artifact-selective:
    DO +RUN_EARTHLY --target=github.com/earthly/test-remote/output/versioned:main+savelocal
    RUN test -f ./output/testfile

dont-save-indirect-remote-artifact:
    DO +RUN_EARTHLY --target=github.com/earthly/test-remote/output/no-version:main+copy-from-savelocal
    RUN test ! -f ./output/testfile
    DO +RUN_EARTHLY --target=github.com/earthly/test-remote/output/versioned:main+copy-from-savelocal
    RUN test ! -f ./output/testfile

push-build:
    DO +RUN_EARTHLY --earthfile=push-build.earth --target=+test --extra_args="--push" --post_command="> output 2>&1"
    RUN cat output
    RUN cat output | perl -pe 'BEGIN {$status=1} END {exit $status} $status=0 if /\+test \| 0\n/;'
    RUN cat output | perl -pe 'BEGIN {$status=1} END {exit $status} $status=0 if /\+run1 \| 1\n/;'
    RUN cat output | perl -pe 'BEGIN {$status=1} END {exit $status} $status=0 if /\+run2 \| 2\n/;'

build-arg-repeat:
    DO +RUN_EARTHLY --earthfile=build-arg-repeat.earth --target=+build-all-1
    RUN test -f ./output/out-other-1
    RUN test -f ./output/out-default-1
    RUN cat ./output/out-other-1 | grep "A=other"
    RUN cat ./output/out-other-1 | grep "B=1"
    RUN cat ./output/out-default-1 | grep "A=default"
    RUN cat ./output/out-default-1 | grep "B=1"
    DO +RUN_EARTHLY --earthfile=build-arg-repeat.earth --target=+build-all-2
    RUN test -f ./output/out-other-1
    RUN test -f ./output/out-default-1
    RUN cat ./output/out-other-1 | grep "A=other"
    RUN cat ./output/out-other-1 | grep "B=1"
    RUN cat ./output/out-default-1 | grep "A=default"
    RUN cat ./output/out-default-1 | grep "B=1"

if:
    RUN touch exists-locally
    DO +RUN_EARTHLY --earthfile=if.earth

for:
    DO +RUN_EARTHLY --earthfile=for.earth

first-command:
    DO +RUN_EARTHLY --earthfile=first-command.earth --target=+all-positive
    DO +RUN_EARTHLY --earthfile=first-command.earth --should_fail=true --target=+start-with-run
    DO +RUN_EARTHLY --earthfile=first-command.earth --should_fail=true --target=+start-with-if
    DO +RUN_EARTHLY --earthfile=first-command.earth --should_fail=true --target=+start-with-non-from-target

platform-output:
    DO +RUN_EARTHLY --earthfile=platform-output.earth
    RUN test -f ./out-arm
    RUN test -f ./out-arm64
    RUN ! test -f ./out-amd64

command:
    RUN echo "hello command" >./message.txt
    DO +RUN_EARTHLY --earthfile=command.earth

command-explicit-global:
    DO +RUN_EARTHLY --earthfile=command-explicit-global.earth

duplicate:
    DO +RUN_EARTHLY --earthfile=duplicate-target-names.earth --should_fail=true --target=+duplicate

reserved:
    DO +RUN_EARTHLY --earthfile=reserved-target-names.earth --should_fail=true --target=+reserved

quotes-test:
    DO +RUN_EARTHLY --earthfile=quotes.earth

new-args:
    DO +RUN_EARTHLY --earthfile=new-args.earth

import:
    DO +RUN_EARTHLY --earthfile=import.earth

infinite-recursion:
    DO +RUN_EARTHLY --earthfile=infinite-recursion.earth --should_fail=true --target=+test1
    DO +RUN_EARTHLY --earthfile=infinite-recursion.earth --should_fail=true --target=+test2
    DO +RUN_EARTHLY --earthfile=infinite-recursion.earth --should_fail=true --target=+test3
    DO +RUN_EARTHLY --earthfile=infinite-recursion.earth --should_fail=true --target=+test4
    DO +RUN_EARTHLY --earthfile=infinite-recursion.earth --should_fail=true --target=+test5
    DO +RUN_EARTHLY --earthfile=infinite-recursion.earth --should_fail=true --target=+test6
    DO +RUN_EARTHLY --earthfile=infinite-recursion.earth --should_fail=true --target=+test7
    DO +RUN_EARTHLY --earthfile=infinite-recursion.earth --should_fail=true --target=+test8

from-dockerfile-arg:
    DO +RUN_EARTHLY --earthfile=from-dockerfile-arg.earth --target=+all
    RUN test "$(cat ./arg-value-default)" = "default"
    RUN test "$(cat ./arg-value-foo)" = "foo"
    RUN test "$(cat ./arg-value-bar)" = "bar"

cache-mount-arg:
    DO +RUN_EARTHLY --earthfile=cache-mount-arg.earth --use_tmpfs=false --target="+b-nomount --MYARG=123"
    DO +RUN_EARTHLY --earthfile=cache-mount-arg.earth --use_tmpfs=false --target="+b-nomount --MYARG=1234" --post_command="2>output-nomount.txt"
    RUN cat output-nomount.txt
    RUN cat output-nomount.txt | grep '\*cached\* --> RUN echo Doing something 1'
    RUN cat output-nomount.txt | grep '\*cached\* --> RUN echo Doing something 2'; test "$?" != 0
    DO +RUN_EARTHLY --earthfile=cache-mount-arg.earth --use_tmpfs=false --target="+b --MYARG=abc"
    DO +RUN_EARTHLY --earthfile=cache-mount-arg.earth --use_tmpfs=false --target="+b --MYARG=abcd" --post_command="2>output.txt"
    RUN cat output.txt
    RUN cat output.txt | grep '\*cached\* --> RUN echo Doing something 1'
    RUN cat output.txt | grep '\*cached\* --> RUN echo Doing something 2'; test "$?" != 0
    DO +RUN_EARTHLY --earthfile=cache-mount-arg.earth --use_tmpfs=false --target="+b-with-arg --MYARG=def"
    DO +RUN_EARTHLY --earthfile=cache-mount-arg.earth --use_tmpfs=false --target="+b-with-arg --MYARG=defg" --post_command="2>output.txt"
    RUN cat output.txt
    RUN cat output.txt | grep '\*cached\* --> RUN echo Doing something 1'; test "$?" != 0
    RUN cat output.txt | grep '\*cached\* --> RUN echo Doing something 2'; test "$?" != 0

true-false-flag:
    DO +RUN_EARTHLY --earthfile=true-false-flag.earth --extra_args="--allow-privileged" --post_command=">output.txt 2>&1"
    RUN cat output.txt
    # test that the two privileged commands were run
    RUN test $( cat output.txt | grep -v echo | grep "I have the power" | wc -l) = "2"
    # test a single non-privileged RUN was executed
    RUN test $( cat output.txt | grep -v echo | grep "fight the power" | wc -l) = "1"

true-false-flag-invalid:
    DO +RUN_EARTHLY --earthfile=true-false-flag-invalid.earth --should_fail=true --target=+run-false --post_command="2>output.txt"
    RUN cat output.txt | grep "Command /bin/sh -c false failed with exit code 1"
    DO +RUN_EARTHLY --earthfile=true-false-flag-invalid.earth --should_fail=true --target=+run-false-with-args --post_command="2>output2.txt"
    RUN cat output2.txt | grep "Command /bin/sh -c 'false echo test' failed with exit code 1"
    DO +RUN_EARTHLY --earthfile=true-false-flag-invalid.earth --should_fail=true --target=+run-maybe --post_command="2>output3.txt"
    RUN cat output3.txt | grep 'invalid argument for flag .*--no-cache.*expected bool'

sequential-locally-test:
    DO +RUN_EARTHLY --earthfile=sequential-locally.earth --use_tmpfs=false --target="+run-lots" --post_command="2>output.txt"
    RUN cat output.txt | grep -vw RUN | grep -vw char | grep -o '\(start\|mid\|end\)\s[a-d]$' > output-filtered.txt
    RUN echo "set -e
expectedmode=\"start\"
expectedchar=\"?\"
while read line; do
    mode=\$(echo \"\$line\" | cut -d \" \" -f1)
    char=\$(echo \"\$line\" | cut -d \" \" -f2)
    echo \"mode=\$mode char=\$char\"
    case \"\$mode\" in
        start)
            test \"\$expectedmode\" = \"start\" || (echo \"expected \$expectedmode; got \$mode\" && exit 1)
            expectedmode=\"mid\"
            expectedchar=\"$char\"
            ;;
        mid)
            test \"\$expectedmode\" = \"mid\" || (echo \"expected \$expectedmode; got \$mode\" && exit 1)
            test \"\$expectedchar\" = \"$char\" || (echo \"expected \$expectedchar; got \$char\" && exit 1)
            # we don't change expectedmode to end, because we can have multiple 'mid's
            ;;
        end)
            test \"\$expectedmode\" = \"mid\" || (echo \"expected \$expectedmode; got \$mode\" && exit 1)
            test \"\$expectedchar\" = \"$char\" || (echo \"expected \$expectedchar; got \$char\" && exit 1)
            expectedmode=\"start\"
            expectedchar=\"?\"
            ;;
        *)
            echo unhandled mode: $mode
            exit 1
    esac
done
echo test passed: RUNs were sequentially grouped
" > test-output.sh && chmod +x test-output.sh
    RUN cat output-filtered.txt | ./test-output.sh

version-flag-test:
    # In addition to testing the --version flag works; this flag is critical for the homebrew deployment test, which
    # performs an assert in https://github.com/earthly/homebrew-earthly/blob/main/Formula/earthly.rb
    RUN earthly --version | grep '^earthly version'
    RUN test "$(earthly --version | wc -l)" = "1"

implicit-ignores:
    RUN mkdir -p ignored notignored && \
        echo "ignored/" > .earthlyignore && \
        echo "test" > notignored/test && \
        echo "test" > ignored/test
    DO +RUN_EARTHLY --earthfile=implicit-ignore.earth
    DO +RUN_EARTHLY --earthfile=no-implicit-ignore.earth

help:
    # tests the hidden `--buildkit-volume-name` flag is only displayed when EARTHLY_SHOW_HIDDEN is enabled
    ENV EARTHLY_SHOW_HIDDEN=0
    RUN earthly --help | grep -v 'buildkit-volume-name'
    ENV EARTHLY_SHOW_HIDDEN=1
    RUN earthly --help | grep 'buildkit-volume-name'

cache-cmd:
    DO +RUN_EARTHLY --earthfile=cache-cmd.earth --target=+test
    DO +RUN_EARTHLY --earthfile=cache-cmd.earth --target=+test-save-artifact
    RUN test "$(cat ./artifacts1/1)" = "artifact 1"
    RUN test -d ./artifacts1/2; test $? = 1
    RUN test "$(cat ./artifacts2/1)" = "artifact 1"
    RUN test "$(cat ./artifacts2/2)" = "artifact 2"
    DO +RUN_EARTHLY --earthfile=cache-cmd.earth --target=+test-no-sharing

ls:
    COPY ls.earth Earthfile
    RUN earthly ls 2>/dev/null | tee actual
    RUN echo -e "+alpha\n+base\n+bravo\n+charlie" > expected
    RUN diff expected actual

ls-subdir:
    COPY ls.earth subdir/Earthfile
    RUN earthly ls ./subdir 2>/dev/null | tee actual
    RUN echo -e "+alpha\n+base\n+bravo\n+charlie" > expected
    RUN diff expected actual

ssh:
    COPY ssh.earth ./Earthfile
    RUN ssh-keygen -b 3072 -t rsa -f /root/rsa-key -q -N '' -C 'rsa-key-from-earthly-tests'
    RUN echo "#!/bin/sh
set -e
eval \"\$(ssh-agent)\"
ssh-add /root/rsa-key
earthly --config \$earthly_config +test
earthly --config \$earthly_config -P +test-with-docker
" >/tmp/test-earthly-script && chmod +x /tmp/test-earthly-script
    ENV EARTHLY_EXEC_CMD="/tmp/test-earthly-script"
    RUN --privileged \
    --entrypoint \
    --mount=type=tmpfs,target=/tmp/earthly \
    -- -P

server:
    HOST api.earthly.dev 127.0.0.1
    ENV EARTHLY_DISABLE_ANALYTICS 1
    RUN \
        echo -e "#!/bin/sh\\ntouch /i-was-run" > /run-this && chmod +x /run-this && \
        nc -l -p 443 -e /run-this & \
        export webserverpid="$!" && \
        earthly +this-will-fail || true && \
        if [ -f /i-was-run ]; then echo "earthly should not have attempted a connection" && exit 1; fi && \
        kill -9 $webserverpid || true

host:
    DO +RUN_EARTHLY --earthfile=host.earth --target=+add-single-host
    DO +RUN_EARTHLY --earthfile=host.earth --target=+add-multiple-host
    DO +RUN_EARTHLY --earthfile=host.earth --target=+add-ipv6

host-invalid:
    DO +RUN_EARTHLY --earthfile=host.earth --should_fail=true --target=+invalid-ip --output_contains="invalid HOST ip"
    DO +RUN_EARTHLY --earthfile=host.earth --should_fail=true --target=+only-host --output_contains="invalid number of arguments for HOST"
    DO +RUN_EARTHLY --earthfile=host.earth --should_fail=true --target=+only-ip --output_contains="invalid number of arguments for HOST"

mtime:
    RUN echo test > file
    DO +RUN_EARTHLY --earthfile=mtime.earth

build-after-from:
    DO +RUN_EARTHLY --earthfile=build-after-from.earth --target=+all
    RUN test -f ./hello.txt

RUN_EARTHLY:
    COMMAND
    ARG earthfile=
    ARG earthfile_dest="./Earthfile"
    ARG target=+all
    ARG extra_args
    ARG pre_command
    ARG post_command
    ARG should_fail=false
    ARG use_tmpfs=true
    ARG exec_cmd=
    ARG output_contains=
    ARG grep_flags=
    IF [ ! -z "$earthfile" ]
        COPY "$earthfile" "$earthfile_dest"
    END
    RUN echo "
        set -x
        export EARTHLY_VERBOSE=1
        if $use_tmpfs; then
            export EARTHLY_TMP_DIR=/tmp/earthly-tmpfs
        fi
        if [ -n \"$pre_command\" ]; then
            eval \"$pre_command\"
        fi
        if [ -n \"$exec_cmd\" ]; then
            if [ \"$exec_cmd\" = \"/tmp/earthly-script\" ]; then
                echo \"exec_cmd cannot be /tmp/earthly-script\"
                exit 1
            fi
            if [ \"$target\" != \"+all\" ]; then
                echo \"target cannot be used with exec_cmd\"
                exit 1
            fi
            export EARTHLY_EXEC_CMD=\"$exec_cmd\"
            echo running earthly with EARTHLY_EXEC_CMD=\$EARTHLY_EXEC_CMD
            (/bin/sh /usr/bin/earthly-entrypoint.sh; echo exit_code=\$?) 2>&1 | tee earthly.output
        else
            echo running earthly with $target
            (eval \"/usr/bin/earthly-entrypoint.sh $extra_args $target $post_command\"; echo exit_code=\$?) 2>&1 | tee earthly.output
        fi

        if ! tail -n 1 earthly.output | grep 'exit_code=[0-9]\+'; then
            echo ERROR: failed to extract exit_code # something is wrong with the above sh script
            exit 1
        fi
        exit_code=\$(tail -n 1 earthly.output | cut -d \"=\" -f2)

        if [ \$exit_code -eq 6 ]; then
            echo =================== Buildkit logs ===================
            cat /var/log/buildkitd.log
            echo ================= End Buildkit logs =================
            exit \$exit_code
        fi

        if $should_fail; then
            if [ \$exit_code -eq 0 ]; then
                echo ERROR: earthly should have failed but didn\'t.
                exit 1
            fi
        else
            if [ \$exit_code -ne 0 ]; then
                echo ERROR: earthly failed with exit code \$exit_code.
                exit \$exit_code
            fi
        fi
        if [ -n \"$output_contains\" ]; then
            if ! grep $grep_flags \"$output_contains\" earthly.output >/dev/null; then
                echo ERROR: earthly output did not contain \\\"$output_contains\\\"
                exit 1
            fi
        fi
    " >/tmp/earthly-script
    RUN --privileged \
        --mount=type=tmpfs,target=/tmp/earthly-tmpfs \
        /bin/sh /tmp/earthly-script
